package com.umeox.stopwatch

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.Intent
import android.os.Bundle
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import androidx.core.os.ConfigurationCompat
import androidx.lifecycle.MutableLiveData
import com.umeox.moto.common.extension.mutableLiveDataOf
import com.umeox.moto.watch.themes.widget.wheel.NumericWheelAdapter
import com.umeox.moto.watch.themes.widget.wheel.WheelView
import com.umeox.moto.watch.themes.app.ThemeAppCompatActivity
import com.umeox.moto.watch.themes.skin.loader.ResourceManager
import com.umeox.stopwatch.databinding.StopwatchLayoutBinding
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import java.util.concurrent.TimeUnit
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds

class CountdownActivity : ThemeAppCompatActivity() {
    private lateinit var binding: StopwatchLayoutBinding
    private val clock = Stopwatch.createUnstarted()
    private var disposable: Disposable? = null
    private var totalTime = 0

    private var remainTime: Int by mutableLiveDataOf(0) {
        val progress = it?.toInt() ?: 0
        binding.tvTime.text = getTimeStr(progress)
        binding.progress.progress = progress
    }

    /** 状态枚举 */
    enum class State {
        /** 配置倒计时 */
        CONFIG,

        /** 倒计时进行中 */
        RUNNING,

        /** 倒计时暂停或结束 */
        HOLDING
    }

    private var state = MutableLiveData(State.CONFIG)
    private var curWheel: WheelView? = null

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = StopwatchLayoutBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val wheelAdapter = NumericWheelAdapter(0, 59, "%02d")
        binding.wheelHour.apply {
            PADDING = 0
            cyclic = true
            adapter = wheelAdapter
        }
        binding.wheelMinute.apply {
            PADDING = 0
            cyclic = true
            adapter = wheelAdapter
        }
        binding.wheelSecond.apply {
            PADDING = 0
            cyclic = true
            adapter = wheelAdapter
        }

        binding.wheelHour.setOnTouchListener { v, event ->
            if (event.action == MotionEvent.ACTION_DOWN) onWheelSelect(v as WheelView)
            return@setOnTouchListener v.onTouchEvent(event)
        }
        binding.wheelMinute.setOnTouchListener { v, event ->
            if (event.action == MotionEvent.ACTION_DOWN) onWheelSelect(v as WheelView)
            return@setOnTouchListener v.onTouchEvent(event)
        }
        binding.wheelSecond.setOnTouchListener { v, event ->
            if (event.action == MotionEvent.ACTION_DOWN) onWheelSelect(v as WheelView)
            return@setOnTouchListener v.onTouchEvent(event)
        }

        state.observe(this) {
            refreshState()
        }

        binding.progress.trackCornerRadius = 5

        binding.btnStart.setOnClickListener {
            //使用设置的时间开始倒计时
            totalTime = getCountTime()
            if (totalTime == 0) return@setOnClickListener
            remainTime = totalTime
            binding.progress.max = totalTime
            start()
            state.value = State.RUNNING
        }

        binding.btnRun.setOnClickListener {
            if (state.value == State.RUNNING) {
                //暂停倒计时
                pause()
                state.value = State.HOLDING
            } else if (state.value == State.HOLDING) {
                //开始倒计时
                if (remainTime == 0) {
                    //倒计时已结束，跳转到设置
                    state.value = State.CONFIG
                } else {
                    //继续倒计时
                    start()
                    state.value = State.RUNNING
                }
            }
        }

        binding.btnStop.setOnClickListener {
            //停止倒计时并跳转到设置
            stop()
            remainTime = 0
            state.value = State.CONFIG
        }
    }

    private fun onWheelSelect(view: WheelView) {
        if (view == curWheel) return
        val res = ResourceManager.getInstance()

        val colorNormal = res.getColor(R.color.color_wheel_value_normal)
        curWheel?.valueTextColor = colorNormal
        curWheel?.invalidate()

        val colorSelected = res.getColor(R.color.color_wheel_value_selected)
        view.valueTextColor = colorSelected
        view.invalidate()
        curWheel = view
    }

    private var initFlag = false
    override fun onResume() {
        super.onResume()
        if (initFlag) return
        //默认10秒倒计时
        binding.wheelSecond.setCurrentItem(10, true)
        initFlag = true
    }

    /** 根据状态刷新界面 */
    private fun refreshState() {
        val state = state.value ?: return
        when (state) {
            State.CONFIG -> {
                binding.viewConfig.visibility = View.VISIBLE
                binding.viewRun.visibility = View.GONE
            }

            State.RUNNING -> {
                binding.viewConfig.visibility = View.GONE
                binding.viewRun.visibility = View.VISIBLE
                binding.btnRun.setBackgroundResource(R.drawable.ic_pause)
            }

            State.HOLDING -> {
                binding.viewConfig.visibility = View.GONE
                binding.viewRun.visibility = View.VISIBLE
                binding.btnRun.setBackgroundResource(R.drawable.ic_start)
            }
        }
    }

    /** 获取设置的时间转换成毫秒值 */
    private fun getCountTime(): Int {
        val hours = binding.wheelHour.currentItem.hours
        val minute = binding.wheelMinute.currentItem.minutes
        val second = binding.wheelSecond.currentItem.seconds
        return (hours + minute + second).inWholeMilliseconds.toInt()
    }

    /** 获取格式化时间字符串 */
    private fun getTimeStr(time: Int): String {
        val duration = time.milliseconds
        return duration.toComponents { hours, minutes, seconds, nanoseconds ->
            val locale = ConfigurationCompat.getLocales(resources.configuration)[0]
            String.format(locale, "%02d:%02d:%02d", hours, minutes, seconds)
        }
    }

    private var alarmIntent: PendingIntent? = null

    private fun keepWake() {
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }

    private fun releaseWake() {
        window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }

    /** 开始倒计时 */
    private fun start() {
        keepWake()
        val remain = remainTime
        if (remain > 0) {
            clock.start()
            Observable
                .interval(30, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .map { clock.elapsed(TimeUnit.MILLISECONDS) }
                .subscribe(mObserver)
        }
    }

    /** 暂停倒计时 */
    private fun pause() {
        disposable?.dispose()
        clock.pause()
    }

    /** 结束倒计时 */
    private fun stop() {
        disposable?.dispose()
        clock.stop()
    }

    private val mObserver: Observer<Long> = object : Observer<Long> {
        override fun onSubscribe(d: Disposable) {
            disposable = d
        }

        override fun onNext(time: Long) {
            val remain = totalTime - time.toInt()
            if (remain > 0) {
                remainTime = remain
            } else {
                remainTime = 0
                state.value = State.HOLDING
                stop()
                releaseWake()
                startActivity(Intent(this@CountdownActivity, TimeUpActivity::class.java))
            }
        }

        override fun onError(e: Throwable) {
        }

        override fun onComplete() {
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        stop()
        releaseWake()
    }
}
